package com.kifas.controller;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import javax.xml.bind.JAXBElement;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import com.kifas.entity.BarangEntity;
import com.kifas.entity.CustomerEntity;
import com.kifas.entity.GudangEntity;
import com.kifas.entity.JenisBarangEntity;
import com.kifas.entity.PenjualanDetailEntity;
import com.kifas.entity.PenjualanEntity;
import com.kifas.entity.SalesEntity;
import com.kifas.model.xml.BarangModel;
import com.kifas.model.xml.CustomerModel;
import com.kifas.model.xml.GudangModel;
import com.kifas.model.xml.JenisBarangModel;
import com.kifas.model.xml.JenisCustomerModel;
import com.kifas.model.xml.PenjualanDetailModel;
import com.kifas.model.xml.PenjualanModel;
import com.kifas.model.xml.PersistStatus;
import com.kifas.model.xml.SalesModel;
import com.kifas.model.xml.SatuanModel;
import com.kifas.service.EntityServiceManager;
import com.kifas.utils.TransactionReferencePopulator;

@Component
@Scope("prototype")
@Path("/Penjualans")
public class PenjualanController {

	private static Logger log = Logger.getLogger(CustomerController.class);

	@Context
	UriInfo uriInfo;

	@Autowired
	private EntityServiceManager entityManager;

	@POST
	@Produces(MediaType.APPLICATION_XML)
	@Consumes(MediaType.APPLICATION_XML)
	public PersistStatus persist(JAXBElement<PenjualanModel> xml) {
		PenjualanModel model = xml.getValue();
		CustomerEntity customerEntity = entityManager.getCustomer(Long.valueOf(model.getCustomer().getIdCustomer()));
		SalesEntity salesEntity = entityManager.getSales(Long.valueOf(model.getSales().getIdSales()));
		Set<PenjualanDetailEntity> penjualanDetailEntities = new HashSet<PenjualanDetailEntity>();
		for (PenjualanDetailModel detail : model.getPenjualanDetails()) {
			PenjualanDetailEntity detailEntity = new PenjualanDetailEntity();
			BarangEntity barangEntity = entityManager.getBarang(detail.getBarang().getIdBarang());
			GudangEntity gudangEntity = entityManager.getGudang(detail.getGudang().getIdMasterGudang());
			detailEntity.setIdDetailPenjualan(null);
			detailEntity.setBarang(barangEntity);
			detailEntity.setGudang(gudangEntity);
			detailEntity.setPrice(detail.getPrice());
			detailEntity.setQty(detail.getQty());
			detailEntity.setSubTotal(detail.getSubTotal());
			detailEntity.setBulanKadaluarsa(detail.getBulanKadaluarsa());
			detailEntity.setPajak(detail.getPajak());
			detailEntity.setDiscount(detail.getDiscount());
			penjualanDetailEntities.add(detailEntity);
		}
		PenjualanEntity penjualanEntity = new PenjualanEntity(null, model.getNoPenjualan(), customerEntity, salesEntity, model.getTanggal(),
				model.getIsPajak(), model.getAlamatKirim(), model.getTotal(), model.getTanggalKirim(), model.getTanggalJatuhTempo(), model.getKeterangan(),
				penjualanDetailEntities, model.getBiayaLain(), model.getNomorPo(), model.getCreatedBy(), model.getCreatedDate());
		for (PenjualanDetailEntity detail : penjualanDetailEntities) {
			try {
				TransactionReferencePopulator referencePopulator = new TransactionReferencePopulator();
				String hashString = referencePopulator.populatePenjualanHash(penjualanEntity.getNoPenjualan(), penjualanEntity.getTanggal(),
						String.valueOf(penjualanEntity.getCustomer().getIdCustomer()), String.valueOf(penjualanEntity.getSales().getIdSales()),
						String.valueOf(detail.getBarang().getIdBarang()), detail.getBulanKadaluarsa());
				if (entityManager.isTransactionStokByReferenceExist(hashString)) {
					log.error("reference is exist");
					return new PersistStatus("PenjualanEntity", "failed", "reference not valid");
				}
			} catch (Exception e) {
				log.error("exception catched", e);
				return new PersistStatus("PenjualanEntity", "failed", "reference not valid");
			}
			detail.setPenjualan(penjualanEntity);
		}
		try {
			entityManager.persist(penjualanEntity);
		} catch (Exception e) {
			e.printStackTrace();
			return new PersistStatus("PenjualanEntity", "failed", "persisting error");
		}
		return new PersistStatus("PenjualanEntity", "success", "success");
	}

	@GET
	@Produces(MediaType.TEXT_XML)
	public List<PenjualanModel> getPenjualans() {
		List<PenjualanEntity> listPenjualansEntity = entityManager.getPenjualans();
		return getPenjualanModels(listPenjualansEntity);
	}

	@GET
	@Path("Closed/{isclose}")
	@Produces(MediaType.TEXT_XML)
	public List<PenjualanModel> getPenjualans(@PathParam("isclose") boolean isclose) {
		List<PenjualanEntity> listPenjualansEntity = entityManager.getPenjualansIsClosed(isclose);
		return getPenjualanModels(listPenjualansEntity);
	}

	@GET
	@Path("Customer/{id}")
	@Produces(MediaType.APPLICATION_XML)
	public List<PenjualanModel> getPenjualanByCustomer(@PathParam("id") Long customerId) {
		CustomerEntity customerEntity = entityManager.getCustomer(customerId);
		List<PenjualanEntity> listPenjualansEntity = entityManager.getPenjualans(customerEntity);
		return getPenjualanModels(listPenjualansEntity);
	}

	@GET
	@Produces(MediaType.TEXT_XML)
	@Path("Sales/{id}")
	public List<PenjualanModel> getPenjualanBySales(@PathParam("id") Long salesId) {
		SalesEntity salesEntity = entityManager.getSales(salesId);
		List<PenjualanEntity> listPenjualansEntity = entityManager.getPenjualans(salesEntity);
		return getPenjualanModels(listPenjualansEntity);
	}

	@GET
	@Path("Date")
	@Produces(MediaType.TEXT_XML)
	public List<PenjualanModel> getPenjualanByDate(@QueryParam("startDate") String startDate, @QueryParam("endDate") String endDate) {
		DateFormat df = new SimpleDateFormat("ddMMyyyy");
		List<PenjualanEntity> listPenjualansEntity = new ArrayList<PenjualanEntity>();
		try {
			listPenjualansEntity = entityManager.getPenjualans(df.parse(startDate), df.parse(endDate));
		} catch (ParseException ex) {
			log.error(ex);
		}
		return getPenjualanModels(listPenjualansEntity);
	}

	@GET
	@Path("Date/SentStatus")
	@Produces(MediaType.TEXT_XML)
	public List<PenjualanModel> getPenjualanByDateUnsent(@QueryParam("startDate") String startDate, @QueryParam("endDate") String endDate,
			@QueryParam("sentStatus") boolean sentStatus) {
		DateFormat df = new SimpleDateFormat("ddMMyyyy");
		List<PenjualanEntity> listPenjualansEntity = new ArrayList<PenjualanEntity>();
		try {
			listPenjualansEntity = entityManager.getPenjualans(df.parse(startDate), df.parse(endDate), sentStatus);
		} catch (ParseException ex) {
			log.error(ex);
		}
		return getPenjualanModels(listPenjualansEntity);
	}

	@GET
	@Path("Date/JthTempo")
	@Produces(MediaType.TEXT_XML)
	public List<PenjualanModel> getPenjualanJthTempo(@QueryParam("startDate") String startDate) {
		DateFormat df = new SimpleDateFormat("ddMMyyyy");
		List<PenjualanEntity> listPenjualansEntity = new ArrayList<PenjualanEntity>();
		try {
			listPenjualansEntity = entityManager.getPenjualansJthTempo(df.parse(startDate));
		} catch (ParseException ex) {
			log.error(ex);
		}
		return getPenjualanModels(listPenjualansEntity);
	}

	@GET
	@Path("Unsent")
	@Produces(MediaType.TEXT_XML)
	public List<PenjualanModel> getUnsentPenjualan() {
		List<PenjualanEntity> listPenjualansEntity = entityManager.getUnsentPenjualans();
		return getPenjualanModels(listPenjualansEntity);
	}

	@POST
	@Path("Status/Closed/{id}")
	@Produces(MediaType.APPLICATION_XML)
	public PersistStatus setClosed(@PathParam("id") Long idPenjualan) {
		try {
			entityManager.updatePenjualanToClosed(idPenjualan);
		} catch (Exception e) {
			log.error("can not update penjualan", e);
			return new PersistStatus("PenjualanEntity", "failed", "can not update penjualan");
		}
		return new PersistStatus("PenjualanEntity", "success");
	}

	protected List<PenjualanModel> getPenjualanModels(List<PenjualanEntity> penjualanEntities) {
		List<PenjualanModel> penjualans = new ArrayList<PenjualanModel>();
		for (PenjualanEntity penjualanEntity : penjualanEntities) {
			// SalesEntity salesEntity = penjualanEntity.getSales();
			CustomerEntity customerEntity = penjualanEntity.getCustomer();
			Set<PenjualanDetailEntity> penjualanDetailEntities = new HashSet<PenjualanDetailEntity>(entityManager.getPenjualanDetailEntities(penjualanEntity));
			SalesModel sales = new SalesModel(customerEntity.getSales().getIdSales(), customerEntity.getSales().getNama(), customerEntity.getSales().getType(), customerEntity.getCreatedBy());
			JenisCustomerModel j = new JenisCustomerModel(customerEntity.getJenisCustomer().getIdJenisCustomer(), customerEntity.getJenisCustomer()
					.getJenisCustomer(), customerEntity.getCreatedBy());
			CustomerModel customer = new CustomerModel(customerEntity.getIdCustomer(), customerEntity.getNama(), customerEntity.getAlamat1(),
					customerEntity.getAlamat2(), customerEntity.getNoTelp(), customerEntity.getEmail(), customerEntity.getContactPerson(), j,
					customerEntity.getAlamat3(), customerEntity.getNoTelp1(), customerEntity.getNoTelp2(), customerEntity.getContactPerson1(),
					customerEntity.getFax(), customerEntity.getNpwp(), customerEntity.getBank_acc(), customerEntity.getTgl_entry(), sales, customerEntity.getCreatedBy());
			Set<PenjualanDetailModel> penjualanDetailModels = new HashSet<PenjualanDetailModel>();
			for (PenjualanDetailEntity penjualanDetail : penjualanDetailEntities) {
				BarangEntity barangEntity = penjualanDetail.getBarang();
				JenisBarangEntity jenisBarangEntity = barangEntity.getJenisBarang();
				JenisBarangModel jenisBarangModel = new JenisBarangModel(jenisBarangEntity.getIdJenisBarang(), jenisBarangEntity.getJenis(), jenisBarangEntity.getCreatedBy());
				SatuanModel satuanModel = new SatuanModel(barangEntity.getSatuan().getIdSatuan(), barangEntity.getSatuan().getSatuan(), barangEntity.getSatuan().getCreatedBy());
				BarangModel barangModel = new BarangModel(barangEntity.getIdBarang(), barangEntity.getKdBarang(), jenisBarangModel, satuanModel,
						barangEntity.getNama(), barangEntity.getHargaBeli(), barangEntity.getHargaJual(), barangEntity.getCreatedBy());
				GudangEntity gudangEntity = penjualanDetail.getGudang();
				GudangModel gudangModel = new GudangModel(gudangEntity.getIdGudang(), gudangEntity.getNamaGudang(), gudangEntity.getLokasi(),
						gudangEntity.getKapasitas(), gudangEntity.getPetugas(), gudangEntity.getAlamat(), gudangEntity.getKode(), gudangEntity.getNotelp(),
						gudangEntity.getTgl_jth_tempo(), gudangEntity.getCreatedBy());
				PenjualanDetailModel penjualanDetailModel = new PenjualanDetailModel(penjualanDetail.getIdDetailPenjualan(), barangModel,
						penjualanDetail.getQty(), penjualanDetail.getPrice(), satuanModel, gudangModel, penjualanDetail.getSubTotal(),
						penjualanDetail.getDiscount(), penjualanDetail.getPajak(), penjualanDetail.getBulanKadaluarsa(), penjualanDetail.getCreatedBy());
				penjualanDetailModels.add(penjualanDetailModel);
			}
			PenjualanModel model = new PenjualanModel(penjualanEntity.getIdPenjualan(), penjualanEntity.getNoPenjualan(), customer, sales,
					penjualanDetailModels, new Timestamp(penjualanEntity.getTanggal().getTime()), penjualanEntity.getIsPajak(),
					penjualanEntity.getAlamatKirim(), penjualanEntity.getTotal(), penjualanEntity.getTanggalKirim(), penjualanEntity.getTanggalJatuhTempo(),
					penjualanEntity.getKeterangan(), penjualanEntity.getBiayaLain(), penjualanEntity.getCreatedBy(), penjualanEntity.getCreatedDate());
			penjualans.add(model);
		}
		return penjualans;
	}

}
